package base.factory.impl;

import base.entity.regitem.DirRegItem;
import base.entity.regitem.FileRegItem;
import base.entity.regitem.RegItem;
import base.factory.Factory;
import base.util.RegItemUtils;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * RegItem的工厂类
 * @Author: x1aolone
 * @Date: 2019/10/1 11:33
 */
public class RegItemFactory implements Factory<RegItem> {

    /**
     * 通过getInstance()获取工厂的实例，实现工厂的单例
     * @return 工厂的实例
     */
    public static RegItemFactory getInstance () {
        return RegItemFactoryInstance.instance;
    }

    @Override
    public RegItem newDirInstance(byte[] bytes) {
        // 数组长度不满足要求，返回null
        if (bytes.length != 8) {
            System.err.println("传入数组长度不为8");
            return null;
        }
        // 目录登记项，type和length是固定值
        RegItem dirRegItem = newDirInstance(new String(bytes, 0, 3), bytes[5], bytes[6]);
        return dirRegItem;
    }

    @Override
    public RegItem newDirInstance(String name, byte property, byte beginFatNum) {
        // 传入的type和length并没有用到，在实际构造的方法时直接使用常量代替
        RegItem dirRegItem = null;
        // 通过反射构建没有内容的对象
        try {
            Constructor constructor = dirRegItemClass.getDeclaredConstructor(String.class,
                    byte.class, byte.class);
            constructor.setAccessible(true);

            boolean nameIsOk = RegItemUtils.fieldIsApproved(String.class, name, 3, 3);
            boolean propertyIsOk = RegItemUtils.fieldIsApproved(byte.class, property, 0, 127);
            boolean beginFatNumIsOk = RegItemUtils.fieldIsApproved(byte.class, property, 0, 127);

            if (nameIsOk && propertyIsOk && beginFatNumIsOk) {
                dirRegItem = (RegItem) constructor.newInstance(name, property, beginFatNum);
            }

        } catch (InstantiationException | NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return dirRegItem;
    }

    @Override
    public RegItem newFileInstance(byte[] bytes) {
        // 数组长度不满足要求，返回null
        if (bytes.length != 8) {
            System.err.println("传入数组长度不为8");
            return null;
        }
        // 目录登记项，type和length是固定值
        RegItem fileRegItem = newFileInstance(new String(bytes, 0, 3), new String(bytes, 3, 2) ,
                bytes[5], bytes[6], bytes[7]);
        return fileRegItem;
    }

    @Override
    public RegItem newFileInstance(String name, String type, byte property, byte beginFatNum, byte length) {
        RegItem fileRegItem = null;
        // 通过反射构建没有内容的对象
        try {
            Constructor constructor = fileRegItemClass.getDeclaredConstructor(String.class,
                    String.class, byte.class, byte.class, byte.class);
            constructor.setAccessible(true);
            // setAccessible的有效范围
            // 全局？×
            // 单个方法？×
            // 单个对象？√
            // 单次调用？×
            boolean nameIsOk = RegItemUtils.fieldIsApproved(String.class, name, 3, 3);
            boolean typeIsOk = RegItemUtils.fieldIsApproved(String.class, type, 2, 2);
            boolean propertyIsOk = RegItemUtils.fieldIsApproved(byte.class, property, 0, 127);
            boolean beginFatNumIsOk = RegItemUtils.fieldIsApproved(byte.class, beginFatNum, 0, 127);
            boolean lengthIsOk = RegItemUtils.fieldIsApproved(byte.class, length, 0, 127);

            if (nameIsOk && typeIsOk && propertyIsOk && beginFatNumIsOk && lengthIsOk) {
                fileRegItem = (RegItem) constructor.newInstance(name, type, property, beginFatNum, length);
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return fileRegItem;
    }


    private static final Class dirRegItemClass = DirRegItem.class;

    private static final Class fileRegItemClass = FileRegItem.class;

    private static class RegItemFactoryInstance {
        /**
         * 使用静态内部类，让JVM来保证线程安全
         */
        private static RegItemFactory instance = new RegItemFactory();
    }

    /**
     * 构造方法私有化，只能通过getInstance来获取工厂实例
     */
    private RegItemFactory () {}


}
